package com.tempjob.common.utils;

import java.util.*;

/**
 * @author hui
 * @Date 2024/3/29 14:58
 **/
public class SimilarityCalculator {

    public static void main(String[] args) {
        List<String> phrases = Arrays.asList(
                "网络信号不稳定，经常断网",
                "网络连接时常中断",
                "网络速度慢",
                "投诉内容：网络信号不稳定，经常断网",
                "网络问题",
                "网络连接失败",
                "网络异常",
                "网络服务不稳定"
        );

        List<String> similarPhrases = extractSimilarPhrases(phrases, 0.8);
        System.out.println("相似度大于0.8且出现频次高到低的短语：");
        for (String phrase : similarPhrases) {
            System.out.println(phrase);
        }
    }

    public static List<String> extractSimilarPhrases(List<String> phrases, double similarityThreshold) {
        // 构建短语的频次统计
        Map<String, Integer> phraseFrequency = new HashMap<>();
        for (String phrase : phrases) {
            phraseFrequency.put(phrase, phraseFrequency.getOrDefault(phrase, 0) + 1);
        }

        // 计算相似度
        Map<String, Double> similarityScores = new HashMap<>();
        for (String phrase1 : phraseFrequency.keySet()) {
            for (String phrase2 : phraseFrequency.keySet()) {
                if (!phrase1.equals(phrase2) && !similarityScores.containsKey(phrase1 + "#" + phrase2)) {
                    double similarity = calculateSimilarity(phrase1, phrase2);
                    similarityScores.put(phrase1 + "#" + phrase2, similarity);
                }
            }
        }

        // 按相似度和频次排序
        List<Map.Entry<String, Double>> sortedSimilarities = new ArrayList<>(similarityScores.entrySet());
        sortedSimilarities.sort((entry1, entry2) -> {
            int compare = Double.compare(entry2.getValue(), entry1.getValue());
            if (compare == 0) {
                return Integer.compare(phraseFrequency.get(entry2.getKey().split("#")[0]),
                        phraseFrequency.get(entry1.getKey().split("#")[0]));
            }
            return compare;
        });

        // 获取相似度大于阈值且出现频次高到低的短语
        List<String> similarPhrases = new ArrayList<>();
        for (Map.Entry<String, Double> entry : sortedSimilarities) {
            String[] phrasesPair = entry.getKey().split("#");
            if (entry.getValue() > similarityThreshold &&
                    !similarPhrases.contains(phrasesPair[0]) &&
                    phraseFrequency.get(phrasesPair[0]) > 1) { // 只保留出现频次大于1的短语
                similarPhrases.add(phrasesPair[0] + ", 频次：" + phraseFrequency.get(phrasesPair[0]) + ", 相似度：" + entry.getValue());
            }
            if (entry.getValue() > similarityThreshold &&
                    !similarPhrases.contains(phrasesPair[1]) &&
                    phraseFrequency.get(phrasesPair[1]) > 1) { // 只保留出现频次大于1的短语
                similarPhrases.add(phrasesPair[1] + ", 频次：" + phraseFrequency.get(phrasesPair[1]) + ", 相似度：" + entry.getValue());
            }
        }

        return similarPhrases;
    }

    // 计算字符串相似度（这里简单地使用Levenshtein距离）
    private static double calculateSimilarity(String str1, String str2) {
        int[][] dp = new int[str1.length() + 1][str2.length() + 1];
        for (int i = 0; i <= str1.length(); i++) {
            dp[i][0] = i;
        }
        for (int j = 0; j <= str2.length(); j++) {
            dp[0][j] = j;
        }
        for (int i = 1; i <= str1.length(); i++) {
            for (int j = 1; j <= str2.length(); j++) {
                if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    dp[i][j] = 1 + Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]);
                }
            }
        }
        return 1.0 - (double) dp[str1.length()][str2.length()] / Math.max(str1.length(), str2.length());
    }


}
